#include <iostream>
#include <memory>
#include <string>

#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/strings/str_format.h"

#include <grpcpp/ext/proto_server_reflection_plugin.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/health_check_service_interface.h>

#include "greet.pb.h"
#include "greet.grpc.pb.h"

ABSL_FLAG(uint16_t, port, 8888, "Server port for the service");

class GreeterServiceImpl final : public greeting::Greeter::Service {
    // unary_unary 
    ::grpc::Status SayHello(::grpc::ServerContext* context, 
                                  const ::greeting::HelloRequest* request, 
                                  ::greeting::HelloReply* response)  override {
        std::string prefix("Hello, ");
        response->set_message(prefix + request->name());
        return ::grpc::Status::OK;
    }

    // unary_stream
    ::grpc::Status SayHelloStreamReply(::grpc::ServerContext* context, 
                                  const ::greeting::HelloRequest* request, 
                                  ::grpc::ServerWriter< ::greeting::HelloReply>* writer
                                ) override 
                                {
        
        return ::grpc::Status::OK;
    }
    
    
    // stream_stream
    ::grpc::Status SayHelloBidiStream(::grpc::ServerContext* context, 
                                ::grpc::ServerReaderWriter< ::greeting::HelloReply, 
                                ::greeting::HelloRequest>* stream) override {
        
        return ::grpc::Status::OK;
    }
};

void serve(uint16_t port) {
    std::string bind_addr = absl::StrFormat("0.0.0.0:%d", port);
    GreeterServiceImpl service;

    grpc::EnableDefaultHealthCheckService(true);
    grpc::reflection::InitProtoReflectionServerBuilderPlugin();
   
    ::grpc::ServerBuilder builder;
    builder.AddListeningPort(bind_addr, grpc::InsecureServerCredentials());
    builder.RegisterService(&service);

    std::unique_ptr<::grpc::Server>  server(builder.BuildAndStart());
    std::cout << "Server listening on " << bind_addr << std::endl;
    server->Wait();
}

int main(int argc, char** argv) {
    absl::ParseCommandLine(argc, argv);
    serve(absl::GetFlag(FLAGS_port));           // 获取预定义的端口
    return 0;
}